import 'package:casdon/modules/recipe/data/model/recipe_category_model.dart';
import 'package:casdon/modules/recipe/domain/states/recipe_category_state.dart';

import 'package:casdon/modules/recipe/providers/recipe_provider.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

class RecipeCategoryNotifier extends AsyncNotifier<RecipeCategoryState> {
  bool _isRefreshing = false;

  @override
  Future<RecipeCategoryState> build() async {
    return _fetchFirstPage();
  }

  Future<void> refresh() async {
    if (_isRefreshing) return;
    _isRefreshing = true;
    final previous = state.valueOrNull;

    try {
      final newState = await _fetchFirstPage();
      state = AsyncValue.data(newState);
    } catch (e, st) {
      if (previous != null) {
        state = AsyncValue.data(previous);
      } else {
        state = AsyncValue.data(RecipeCategoryState.initial());
      }
    } finally {
      _isRefreshing = false;
    }
  }

  Future<void> loadMore() async {
    final current = state.valueOrNull;
    if (current == null || current.isLoadingMore || !current.hasMore) return;

    state = AsyncValue.data(current.copyWith(isLoadingMore: true));
    final nextPage = current.page + 1;

    try {
      final ret = await ref
          .read(recipeCategoryUsecaseProvider)
          .execute(pageNum: nextPage, pageSize: current.pageSize);

      final merged = [
        ...current.data,
        ...RecipeCategoryModel.listFromApi(ret.rows),
      ]..sort((a, b) => a.sort.compareTo(b.sort));

      state = AsyncValue.data(
        current.copyWith(
          data: merged,
          page: nextPage,
          totalSize: ret.total,
          isLoadingMore: false,
          hasMore: ret.total > merged.length,
        ),
      );
    } catch (_) {
      state = AsyncValue.data(current.copyWith(isLoadingMore: false));
    }
  }

  Future<RecipeCategoryState> _fetchFirstPage() async {
    final firstPage = 1;
    const pageSize = 100;
    final previous = state.valueOrNull;

    try {
      final ret = await ref
          .read(recipeCategoryUsecaseProvider)
          .execute(pageNum: firstPage, pageSize: pageSize);
      final data = RecipeCategoryModel.listFromApi(ret.rows)
        ..sort((a, b) => a.sort.compareTo(b.sort));
      return RecipeCategoryState(
        data: data,
        page: firstPage,
        totalSize: ret.total,
        pageSize: pageSize,
        isLoadingMore: false,
        hasMore: ret.total > data.length,
      );
    } catch (_) {
      return previous?.copyWith(isLoadingMore: false) ??
          RecipeCategoryState.initial().copyWith(
            page: firstPage,
            pageSize: pageSize,
            isLoadingMore: false,
          );
    }
  }
}
